package com.haiheng.library_base.mqtt

import com.haiheng.library.log.LogUtils
import com.haiheng.library.log.LogWriter
import com.haiheng.library_base.model.ApplicationViewModel
import com.haiheng.library_base.model.ApplicationViewModel.Companion.get
import com.haiheng.library_base.msg.MsgCode
import com.haiheng.library_base.msg.MsgEvent
import org.eclipse.paho.client.mqttv3.*
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence

/**
 *
 * @Des:
 * @Author: hwz
 * @Date:2023/4/28 0028
 * @Version: 1.0
 */
class MqttConnectionManager(private val clientId: String,private val brokerUrl: String,
                            private val username: String, private val password: String) {
    private lateinit var mqttClient: MqttAsyncClient

    fun connect() {
        try {
            mqttClient = MqttAsyncClient(brokerUrl, clientId, MemoryPersistence())
            val options = MqttConnectOptions()
            options.userName = username
            options.password = password.toCharArray()

            mqttClient.connect(options, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    LogUtils.d(TAG+"onSuccess to connect to MQTT broker: ${asyncActionToken?.response}")
                    //发消息出去
                    val event = MsgEvent()
                    event.code = MsgCode.MSG_MQTT_CONNECT_SUCCESS
                    get().even.postValue(event)
//                subscribe(TOPIC, QOS)
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    LogWriter.e(TAG+"Failed to connect to MQTT brokerUrl: ${brokerUrl} clientId:${clientId} exception: ${exception?.toString()}")
                    val event = MsgEvent()
                    event.code = MsgCode.MSG_MQTT_CONNECT_FAIL
                    event.msg = "连接mqtt失败：${exception?.toString()}"
                    get().even.postValue(event)
                }
            })

            mqttClient.setCallback(object :MqttCallback{
                override fun connectionLost(cause: Throwable?) {
                    LogWriter.e(TAG+"connectionLost  to cause : $cause")


                }

                override fun messageArrived(topic: String?, message: MqttMessage?) {
                    LogWriter.e(TAG+"messageArrived  topic: $topic  message:$message")

                    val event = MsgEvent()
                    event.code = MsgCode.MSG_MQTT_MESSAGE_ARRIVED
                    event.msg =message.toString()
                    event.topic = topic
                    get().even.postValue(event)
                }

                override fun deliveryComplete(token: IMqttDeliveryToken?) {
                    LogUtils.e(TAG+"deliveryComplete token $token")
                }

            })
        }catch (ex:Exception){
            LogWriter.e("连接异常 ex:${ex.message}")
        }
    }

    fun subscribe(topic: String, qos: Int = 1) {
        try {
            mqttClient.subscribe(topic, qos, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    LogUtils.e(TAG+"onSuccess Subscribed  to topic: $topic")



                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    LogWriter.e(TAG+"Failed to subscribe to topic: $topic, error: ${exception?.message}")
                }
            })

        }catch (ex:Exception){
            LogWriter.e(TAG+"Failed to subscribe topic: $topic, error: ${ex?.message}")
        }

    }

    fun publish(topic: String, message: String, qos: Int = 1) {
        try {
            val mqttMessage = MqttMessage(message.toByteArray())
            mqttMessage.qos = qos

            mqttClient.publish(topic, mqttMessage, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    LogWriter.e(TAG+"Message published to topic: $topic, message: $message")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    LogWriter.e("${TAG} TAG+ Failed to publish message to topic: $topic, error: ${exception?.message}")
                }
            })
        }catch (ex:Exception){
            LogWriter.e(" ${TAG} Failed to publish topic: $topic, error: ${ex?.message}")
        }

    }

    fun unsubscribe(topic: String){
        try {
            mqttClient.unsubscribe(topic)

        }catch (ex:Exception){
            LogWriter.e("取消订阅异常：${ex.message}")
        }
    }

    fun disconnect() {
        try {
            if (!mqttClient.isConnected) return
            mqttClient.disconnect()
            mqttClient.close()
            LogUtils.d("${TAG} Disconnected from: $brokerUrl")
        } catch (e: MqttException) {
            e.printStackTrace()
            LogWriter.e("${TAG} Failed to disconnect: $brokerUrl")
        }

    }

    fun reconnect() {
        try {
            connect()
            LogUtils.d("${TAG} Reconnected to: $brokerUrl")
        } catch (e: Exception) {
            LogWriter.e("${TAG} Failed to reconnect: $brokerUrl")
            e.printStackTrace()
        }

    }

    companion object {
        private const val TAG = "MqttConnection"
    }
}